今天我們將在家用品管理 App 的主頁中新增一個側邊欄,來提升 App 的 UX。這個側邊欄不僅能夠方便使用者快速瀏覽不同的物品分類,還可以包含管理、報表、聯絡等選項,幫助使用者更全面地管理物品和帳務。
我們的目標是透過 SwiftUI 建立一個側邊欄 (SlideMenu),讓使用者可以在主頁上輕鬆操作。這個側邊欄將包括以下選項:
在建立側邊欄的內容之前,我們需要先定義一個 MenuItem 結構。這個結構將代表側邊欄中的每個選單項目,包含文字和圖案。
struct MenuItem: Identifiable {
var id = UUID()
let text: String
let icon: String
}
MenuItem 結構定義了每個選單項目的 id(唯一識別碼)、text(顯示的文字)以及 icon(圖案)。我們會在側邊欄的內容中使用這個結構來表示選單項目。
接著,建立側邊欄(MenuContent)的內容,也就是選單項目,放在 MenuContent 中。這樣的設計可以幫助我們將選單的結構與樣式分開,讓程式碼更加清晰和易於維護。
我們先建立一個名為 MenuContent 的 Swift 檔,並宣告我們需要的選項:
struct MenuContent: View {
let items: [MenuItem] = [
MenuItem(text: "管理分類", icon: "square.grid.2x2"),
MenuItem(text: "管理地點", icon: "location"),
MenuItem(text: "帳務報表", icon: "chart.pie"),
MenuItem(text: "給予評分", icon: "star.bubble"),
MenuItem(text: "與我聯絡", icon: "envelope"),
]
var body: some View {
}
}
接下來要來幫我們的側邊欄製作 UI,可以在 Assets 中建立分別為 BgColor 和 FontColor 的顏色後,在程式碼中指定我們的背景顏色與文字顏色:
var body: some View {
ZStack {
Color("BgColor")
VStack(alignment: .leading, spacing: 0) {
ForEach(items) { item in
HStack {
Button(action: {
}, label: {
Image(systemName: item.icon)
Text(item.text)
})
.foregroundColor(Color("FontColor"))
.frame(maxWidth: .infinity)
.font(.headline)
.padding()
.overlay {
RoundedRectangle(cornerRadius: 15)
.stroke(.gray, lineWidth: 2)
}
Spacer()
}
.padding(8)
}
Spacer()
}
}
}
在這段程式碼中,我們使用 ZStack 來設置背景顏色,並且定義側邊欄的每個選項,透過 VStack 將每個按鈕依序排列。ForEach 會迭代 items 陣列中的每個項目,並在畫面上生成對應的按鈕。每個選項都包含一個圖標和文字,設置了點擊動作,並以 RoundedRectangle 做簡單的樣式設定,讓選單看起來更加整齊。
附上完整程式碼:
struct MenuContent: View {
let items: [MenuItem] = [
MenuItem(text: "管理分類", icon: "square.grid.2x2"),
MenuItem(text: "管理地點", icon: "location"),
MenuItem(text: "帳務報表", icon: "chart.pie"),
MenuItem(text: "給予評分", icon: "star.bubble"),
MenuItem(text: "與我聯絡", icon: "envelope"),
]
var body: some View {
ZStack {
Color("BgColor")
VStack(alignment: .leading, spacing: 0) {
ForEach(items) { item in
HStack {
Button(action: {
}, label: {
Image(systemName: item.icon)
Text(item.text)
})
.foregroundColor(Color("FontColor"))
.frame(maxWidth: .infinity)
.font(.headline)
.padding()
.overlay {
RoundedRectangle(cornerRadius: 15)
.stroke(.gray, lineWidth: 2)
}
Spacer()
}
.padding(8)
}
Spacer()
}
}
}
}
接下來,我們需要建立一個名為 SlideMenu 的畫面,這個畫面將負責呈現側邊欄並控制其顯示與隱藏。當 isShowing 為 true 時,側邊欄會從左側滑出,並在背景新增一個半透明的遮罩來強調側邊欄的顯示。
我們先宣告三個變數:isShowing、width、toggleMenu。
struct SlideMenu: View {
@Binding var isShowing: Bool
let width: CGFloat
let toggleMenu: () -> Void
}
接著使用 ZStack 來顯示側邊欄,並建立半透明的背景遮照,且讓它被點擊時需要切換 isShowing 的狀態。因為側邊欄的顯示與隱藏是透過 isShowing 這個綁定的變數來控制的。
var body: some View {
ZStack {
if isShowing {
Rectangle()
.opacity(0.3)
.ignoresSafeArea()
.onTapGesture {
isShowing.toggle()
}
}
}
}
我們現在就可以將剛剛新增好的 MenuContent 新增進來,並且新增顯示的動畫:
import SwiftUI
struct SlideMenu: View {
@Binding var isShowing: Bool
let width: CGFloat
let toggleMenu: () -> Void
var body: some View {
ZStack {
if isShowing {
Rectangle()
.opacity(0.3)
.ignoresSafeArea()
.onTapGesture {
isShowing.toggle()
}
HStack {
VStack(alignment: .leading) {
MenuContent()
Spacer()
}
.padding()
.frame(width: width, alignment: .leading)
.background(Color("BgColor"))
Spacer()
}
.transition(.move(edge: .leading))
}
}
.animation(.easeInOut, value: isShowing)
}
}
#Preview {
SlideMenu(isShowing: .constant(true), width: 370, toggleMenu: {})
}
我們使用 .transition(.move(edge: .leading)) 來讓側邊欄從左側平滑地滑出,增強使用者體驗。關於動畫的詳細說明,我推薦 ChaoCode 的頻道,這一支影片我覺的她介紹的很好 - 動畫的產生 & View 的身份概念 - SwiftUI 新手入門。
最後,我們要將 SlideMenu 整合到 ContentView,並且透過一個按鈕來控制側邊欄的顯示與隱藏。
import SwiftUI
struct ContentView: View {
@State private var isShowMenu = false
var body: some View {
NavigationView {
ZStack {
// 主內容
VStack {
// 這裡放入其他 UI 元件
}
// 將 SlideMenu 加入畫面
SlideMenu(isShowing: $isShowMenu, width: UIScreen.main.bounds.size.width / 1.5, toggleMenu: toggleMenu)
}
.navigationBarHidden(isShowMenu ? true : false)
.navigationTitle("")
.navigationBarItems(
leading: Button(action: {
self.isShowMenu.toggle()
}) {
Image(systemName: "line.horizontal.3")
.foregroundColor(Color("FontColor"))
}
)
.navigationBarTitleDisplayMode(.inline)
}
}
private func toggleMenu() {
isShowMenu.toggle()
}
}
在 ContentView 中,我們使用 @State 來追蹤側邊欄的顯示狀態,並透過上方工具列上的按鈕來控制側邊欄的開關。當按鈕被點擊時,側邊欄會滑出或隱藏,讓使用者可以方便地瀏覽不同的頁面。
我們成功在家用品管理 App 中實作一個自訂的側邊欄。這個側邊欄包含了多個選項,未來希望能夠讓使用者更容易地管理分類、地點,以及查看帳務報表等功能。接下來就讓我們一樣一樣實現這些功能吧!明天見囉!